/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package network;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import schedulingScheme.BatteryExhaustedException;
import schedulingScheme.SensorNode;

/**
 *
 * @author Andrzej
 */
public class DirectCommunication implements Network{
    private List<SensorNode> sensors = new ArrayList<SensorNode>();
    private SensorNode sink;
    private List<NetworkListener> listeners = new ArrayList<NetworkListener>();
    int time = 0;

    public void addSensor(SensorNode s) {
        sensors.add(s);
    }

    public void addSink(SensorNode s) {
        sink = s;
    }

    public void removeSensor(SensorNode s) {
        sensors.remove(s);
    }

    public void addNetworkListener(NetworkListener nl) {
        listeners.add(nl);
    }


    public void start() {

        ArrayList<SensorNode> activeSensors = new ArrayList<SensorNode>(sensors.size());
        reportNetworkReorganized();
        while (sensors.size() > 0) {
            
            //we need another collection because nodes can be added and removed from sensors collection allways
            activeSensors.clear();
            activeSensors.addAll(sensors);
            
            for (SensorNode s : activeSensors) {
                try {
                    if (s.isOn()) {
                        s.sendMessage(sink, MESSAGE_LENGTH);
                    }
                } catch (BatteryExhaustedException ex) {

//                    Logger.getLogger(DirectCommunication.class.getName()).log(Level.SEVERE, null, ex);
                    
                    reportSensorDied(s);
                    sensors.remove(s);
                    
                }

            }
            time++;
            reportTimePassed(time);

        }
        System.out.println(""+time);
        
    }

        private void reportSensorDied(SensorNode s) {
        for (NetworkListener nl : listeners) {
            nl.sensorDied(s, time);
        }
    }

    private void reportTimePassed(int time) {
        for (NetworkListener nl : listeners) {
            nl.timePassed(time);
        }
    }
        private void reportNetworkReorganized() {
        for (NetworkListener nl : listeners) {
            assert(time == 0);
            nl.networkReorganized(0, time);
        }
    }

    public NetworkInfo getNetworkInfo() {
        return new NetworkInfo() {

            public int getSensorRole(SensorNode s) {
                if (sensors.contains(s))
                    return REGULAR_NODE;
                else
                    return NOT_IN_NETWORK;
            }

            public Collection<SensorNode> getSensorsInCluster(SensorNode clusterHead) {
                throw new UnsupportedOperationException("Not supported yet.");
            }

            public Collection<SensorNode> activeSensors() {
                return Collections.unmodifiableCollection(sensors);
            }
        };
    }

}
